#pragma once

#include "DXAMLCommon.h"
#include "xamlwriter.h"
#include "ObjectWriterSettings.h"
#include "XamlOptimizedNodeList.h"
#include "IErrorService.h"
#include "IError.h"

#include "XamlSavedContext.h"


class ObjectWriterContext;
class DeferringWriter;

class ObjectWriter :
	public XamlWriter
{
public:
	enum SkipProcessingStage
	{
		spsNotSkipping = 0x0,
		spsSkipping = 0x1,
	};

private: 
	xshared_ptr<XamlQualifiedObject> m_qoLastInstance;
	xshared_ptr<XamlQualifiedObject> m_qoRootObjectInstance;
	xshared_ptr<XamlQualifiedObject> m_qoEventRoot;
	xshared_ptr<ObjectWriterContext> m_spContext;
	xshared_ptr<XamlType> m_spParamType;
	xshared_ptr<XamlProperty> m_spXKeyProperty;
	xshared_ptr<XamlProperty> m_spXNameProperty;
	xshared_ptr<DeferringWriter> m_spDeferringWriter;
	xshared_ptr<ObjectWriterCallbacksDelegate> m_spObjectWriterCallbacks;
	xref_ptr<INameScope> m_spNameScope;
	XUINT32 m_uiLineNumber;
	XUINT32 m_uiLinePosition;
	XUINT32 m_fInDispose;
	XBOOL m_bExpandTemplates;
	XUINT32 m_skipDepth;
	enum SkipProcessingStage m_skipStage;

private: 
	ObjectWriter();
public: 
	static HRESULT Create(const xshared_ptr<XamlSchemaContext> & spSchemaContext, const xshared_ptr<XamlSavedContext> & spSavedContext, const xshared_ptr<ObjectWriterSettings> & spSettings, XBOOL bExpandTemplates, xshared_ptr<ObjectWriter> & rspObjectWriter);
	static HRESULT Create(const xshared_ptr<XamlSavedContext> & spSavedContext, const xshared_ptr<ObjectWriterSettings> & spSettings, xshared_ptr<ObjectWriter> & rspObjectWriter);
	static HRESULT Create(const xshared_ptr<XamlSavedContext> & spSavedContext, XBOOL bExpandTemplates, xshared_ptr<ObjectWriter> & rspObjectWriter);
	static HRESULT Create(const xshared_ptr<XamlSavedContext> & spSavedContext, xshared_ptr<ObjectWriter> & rspObjectWriter);
	static HRESULT Create(const xshared_ptr<XamlSchemaContext> & spSchemaContext, const xshared_ptr<ObjectWriterSettings> & spSettings, xshared_ptr<ObjectWriter> & rspObjectWriter);


	virtual HRESULT WriteObject(const xshared_ptr<XamlType> & spXamlType, XUINT32 fromMember);
	virtual HRESULT WriteEndObject();
	virtual HRESULT WriteMember(const xshared_ptr<XamlProperty> & spProperty);
	virtual HRESULT WriteEndMember();
	virtual HRESULT WriteValue(const xshared_ptr<XamlQualifiedObject> & value);
	virtual HRESULT WriteNamespace(const xshared_ptr<CXString> & spPrefix, const xshared_ptr<XamlNamespace> & spXamlNamespace);
	HRESULT get_Result(xshared_ptr<XamlQualifiedObject> & rqoOut);
	virtual HRESULT GetSchemaContext(xshared_ptr<XamlSchemaContext> & rspOut);
	XBOOL get_ShouldProvideLineInfo();
	HRESULT SetLineInfo(XINT32 bLine, XINT32 nColumn);
protected: 
	HRESULT OnObjectCreated(const xshared_ptr<XamlQualifiedObject> & qoNewInstance);
	virtual HRESULT ProcessError();
private: 
	HRESULT WriteObjectCore(const xshared_ptr<XamlType> & spXamlType, XUINT32 fromMember);
	HRESULT WriteEndObjectCore();
	HRESULT WriteMemberCore(const xshared_ptr<XamlProperty> & spProperty);
	HRESULT WriteEndMemberCore();
	HRESULT WriteValueCore(const xshared_ptr<XamlQualifiedObject> & value);
	HRESULT WriteNamespaceCore(const xshared_ptr<CXString> & spPrefix, const xshared_ptr<XamlNamespace> & spXamlNamespace);
	HRESULT get_X_KeyProperty(xshared_ptr<XamlProperty> & rspOut);
	HRESULT get_X_NameProperty(xshared_ptr<XamlProperty> & rspOut);
	HRESULT Logic_ShouldWriteMemberCreateWithCtor(XBOOL & fOut);
	HRESULT Logic_CreateWithCtor();
	HRESULT Logic_CreateFromInitializationValue();
	HRESULT Logic_CreatePropertyValueFromText();
	HRESULT Logic_BeginInit();
	HRESULT Logic_EndInit();
	HRESULT Logic_DuplicatePropertyCheck(const xshared_ptr<XamlProperty> & spProperty);
	HRESULT Logic_ApplyCurrentSavedDirectives();
	HRESULT Logic_ProvideValue();
	HRESULT Logic_AssignProvidedValue();
	HRESULT Logic_CheckAssignmentToParentStart();
	HRESULT Logic_DoAssignmentToParentCollection();
	HRESULT Logic_DoAssignmentToParentProperty();
	HRESULT Logic_SetTemplateProperty(const xshared_ptr<XamlOptimizedNodeList> & spNodeList);
	HRESULT Logic_RegisterName_OnCurrent(const xshared_ptr<XamlQualifiedObject> & qoName);
	HRESULT Logic_RegisterName_OnParent(const xshared_ptr<XamlQualifiedObject> & qoName);
	HRESULT RegisterName(const xshared_ptr<XamlQualifiedObject> & qoName, const xshared_ptr<XamlQualifiedObject> & qoInstance, xref_ptr<INameScope> & spNameScope);
	HRESULT RemapDirectiveToProperty(const xshared_ptr<XamlType> & inParentType, const xshared_ptr<XamlProperty> & inDirectiveProperty, xshared_ptr<XamlProperty> & outRemappedProperty);
	HRESULT GetTemplateContentObject(const xshared_ptr<XamlOptimizedNodeList> & spNodeList, xshared_ptr<XamlQualifiedObject> & qoTemplateContent);
	HRESULT ExpandTemplateForInitialValidation(const xshared_ptr<XamlOptimizedNodeList> & spNodeList);
	HRESULT CreateWithCtor(const xshared_ptr<XamlType> & spType, xshared_ptr<XamlQualifiedObject> & spInstance);
	void    UpdateSkipDepthForResource(enum XamlNode::XamlNodeType operationType);
	XBOOL   ShouldSkipForResourceReplacement();
	HRESULT InitiatePropertyReplacementIfNeeded(const xshared_ptr<XamlProperty> & spXamlProperty);
	HRESULT GetPropertyBagIfRequired(const xshared_ptr<XamlProperty> & spXamlProperty, const xshared_ptr<XamlQualifiedObject> & qoInstance);
	HRESULT ApplyRemainingResourceProperties();
	HRESULT GetResourcePropertyBag();
	HRESULT GetErrorService(xshared_ptr<ParserErrorReporter> & outErrorService);

	HRESULT ReportError(XUINT32 errorCode, const XamlLineInfo & inLineInfo, const xshared_ptr<CXString> & inssParam1, const xshared_ptr<CXString> & inssParam2);
	HRESULT ReportError(XUINT32 errorCode, const XamlLineInfo & inLineInfo, const xshared_ptr<CXString> & inssParam1);
	HRESULT ReportError(XUINT32 errorCode, const XamlLineInfo & inLineInfo);


	HRESULT ReportSetValueError(HRESULT errorResult, const XamlLineInfo & inLineInfo, const xshared_ptr<CXString> & inssParam1);
	HRESULT ReportSetValueError(HRESULT errorResult, const XamlLineInfo & inLineInfo, const xshared_ptr<CXString> & inssParam1, const xshared_ptr<CXString> & inssValue);

	HRESULT GetReportedError(xshared_ptr<ParserErrorReporter> & spParserErrorReporter, struct IErrorService * * ppErrorService, struct IError * * ppLastError);
	HRESULT WrapErrorWithParserErrorAndRethrow(HRESULT errorCode);




};

